﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BasicWave
{

    /// <summary>
    /// Questa classe si occupa di ricevere dati da parte delle api
    /// windows WaveIn e poi metterle in coda al buffer presente
    /// nel MasterChannel.
    /// 
    /// </summary>
    public class CMicrophoneChannel :CBaseAudioChannel, IDisposable, IAudioChannel
    {

        Queue<byte> m_fifo = new Queue<byte>();

        private byte[] m_RecBuffer;


        //gestione del recorder
        private WaveLib.WaveInRecorder m_Recorder;


        //QUESTO è la dimensione del buffer che viene restituito ogni volta dalla scheda audio
        //più è alto il valore e più c'è lag fra la ripresa e la riproduzione
        int BUFFER_SIZE = 32768;


        //variabile che memorizza il master....
        CMasterChannel m_master;


        //formato di registrazione
        WaveLib.WaveFormat form;



        //costruttore
        public CMicrophoneChannel(ref CMasterChannel aMaster)
        {
            //assegna la variabile come puntatore alla classse master
            m_master = aMaster;

            //registro il canale sul master
            m_master.RegisteredChan(this);


            form = new WaveLib.WaveFormat(44100, 16, 2);


            //è importante che il buffer rimanga a 16384!
            m_Recorder = new WaveLib.WaveInRecorder(-1, form, BUFFER_SIZE, 3, new WaveLib.BufferDoneEventHandler(DataArrived));
        }




        /// <summary>
        /// Funzione fondamentale per il funzionamento della classe
        /// ogni volta che il buffer è completo...questa funzione viene chiamata
        /// restituendoci tutti i dati catturati fino a questo momento
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="size"></param>
        private void DataArrived(IntPtr data, int size)
        {
            if (m_RecBuffer == null || m_RecBuffer.Length < size)
                m_RecBuffer = new byte[size];



         //questa funzione COPIA UN AReA DI MEMORIA NON GESTITA (ovvero l'input del microfono 
            //in un area di memoria gestita. Lavora in maniera inversa all'altra 
            //utilizzata nel master channel
            System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size);



            //invia i dati al fifo buffer
            lock (m_fifo)
            {

               



                //inserisce dati nel proprio buffer
                for (int i=0;i<m_RecBuffer.Length;i++)
                    m_fifo.Enqueue(m_RecBuffer[i]);
            }
            
            
            //  m_master.EnquedRawData(ref m_RecBuffer, 0, m_RecBuffer.Length);
        }



        /// <summary>
        /// Implementazione dell'interfaccia IAudioChannel
        /// </summary>
        /// <param name="aBuffer"></param>
        /// <param name="size"></param>
        public void FillChunk(ref byte[] aBuffer, int size)
        {
            lock (m_fifo)
            {

                


                for (int i = 0; i < size; i++)
                    if (m_fifo.Count > 0)
                        aBuffer[i] = m_fifo.Dequeue();


                //prima di consegnarli al master.... applicare il volume
                VolumerizeByte(ref aBuffer, size);
            }

        }





        #region IDisposable Members

        public void Dispose()
        {
            if (m_Recorder != null)
                try
                {
                    m_Recorder.Dispose();
                }
                finally
                {
                    m_Recorder = null;
                }

        }

        #endregion

    }
}
